mod actor_ref;
mod basic_actors;
mod lifecycle;
mod decorators;
mod props;
mod builder;
mod mock_actor;
pub use actor_ref::ActorRef;
pub use basic_actors::{ForwardActor, BatchActor};
pub use lifecycle::{ActorLifecycle, LifecycleAware};
pub use decorators::{ThrottleDecorator, RetryDecorator};
pub use props::Props;
pub use mock_actor::MockActor;

use async_trait::async_trait;
use crate::context::Context;
use crate::errors::SendError;
use crate::message::{Message, DynamicMessage};
use std::future::Future;
use std::pin::Pin;

#[async_trait]
pub trait Actor: Send + Sync {
    async fn started(&mut self, _ctx: &Context) -> Result<(), SendError> {
        Ok(())
    }

    async fn stopped(&mut self, _ctx: &Context) -> Result<(), SendError> {
        Ok(())
    }

    async fn receive(&mut self, ctx: &Context, msg: DynamicMessage) -> Result<(), SendError>;
}

pub trait ActorFactory: Send + Sync {
    fn create(&self) -> Box<dyn Actor>;
}

impl<F, A> ActorFactory for F
where
    F: Fn() -> A + Send + Sync,
    A: Actor + 'static,
{
    fn create(&self) -> Box<dyn Actor> {
        Box::new((self)())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::context::Context;
    use crate::message::Message;
    use std::sync::Arc;
    use tokio::sync::mpsc;

    struct TestActor;

    #[async_trait]
    impl Actor for TestActor {
        async fn receive(&mut self, _ctx: &Context, _msg: DynamicMessage) -> Result<(), SendError> {
            Ok(())
        }
    }

    #[tokio::test]
    async fn test_actor_lifecycle() {
        let mut actor = TestActor;
        let (tx, _rx) = mpsc::channel(100);
        let ctx = Context::new(Arc::new(tx));

        assert!(actor.started(&ctx).await.is_ok());
        assert!(actor.stopped(&ctx).await.is_ok());
    }
} 